home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 3 / Amiga Format CD03 (1996-07-04)(Future Publishing)(GB)(Track 1 of 6)[!][issue 1996-08].iso / comms / netsoftware / archie38_1.lha / archie-1.4 / support.c < prev    next >
C/C++ Source or Header  |  1995-01-05  |  22KB  |  831 lines

  1. /*
  2.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  3.  *
  4.  * For copying and distribution information, please see the file
  5.  * <copyright.h>.
  6.  */
  7. /* Amiga port by Tomas Willis (tomas@cae.wisc.edu) January 1995 */
  8.  
  9. /*
  10.  * Miscellaneous routines pulled from ~beta/lib/pfs and ~beta/lib/filters
  11.  */
  12.  
  13. #include <stdio.h>
  14.  
  15. #include <errno.h>
  16.  
  17. #ifdef VMS
  18. # ifdef WOLLONGONG
  19. #  include "twg$tcp:[netdist.include]netdb.h"
  20. # else /* not Wollongong */
  21. #  ifdef UCX
  22. #   include <netdb.h>
  23. #  else /* Multinet */
  24. #   include "multinet_root:[multinet.include]netdb.h"
  25. #  endif
  26. # endif
  27. # include <vms.h>
  28. #else /* not VMS */
  29. # include <sys/types.h>
  30. # include "pmachine.h"
  31. # ifdef NEED_STRING_H
  32. #  include <string.h>
  33. # else
  34. #  include <strings.h>
  35. # endif
  36. # ifndef CUTCP
  37. #  include <netdb.h>
  38. # endif
  39. # if !defined(MSDOS) || defined(OS2)
  40. #  ifndef AMIGA
  41. #   include <sys/file.h>
  42. #  endif /* AMIGA */
  43. #  include <sys/param.h>
  44. # endif
  45. #endif /* VMS */
  46.  
  47. #include "pfs.h"
  48. #include "pprot.h"
  49. #include "perrno.h"
  50. #include "pcompat.h"
  51. #include "pauthent.h"
  52.  
  53. #include "regex.h"
  54.  
  55. int    pfs_enable = PMAP_ATSIGN;
  56.  
  57. #ifndef FALSE
  58. # define TRUE     1
  59. # define FALSE   0
  60. #endif
  61.  
  62. //protos
  63. char *month_sname(int n);
  64. int wcmatch(char *s, char *template);
  65. int ul_insert(VLINK ul, PVDIR vd,VLINK p);
  66. int vl_insert(VLINK vl, PVDIR vd,int allow_conflict);
  67. char * nlsindex(char * s1, char *s2);
  68. char * sindex(char *s1, char * s2);
  69. int scan_error(char * erst);
  70. PATTRIB parse_attribute(char *line);
  71. char * nxtline(char *s);
  72. char * unquote(char *s);
  73. //extern
  74. extern int vl_comp(VLINK vl1, VLINK vl2);
  75. extern int vl_equal(VLINK vl1, VLINK vl2);
  76. extern VLINK vlalloc(void);
  77. extern void vlfree(VLINK vl);
  78. extern PATTRIB atalloc(void);
  79. extern char * stcopy(char *st);
  80. extern char * stcopyr(char *s, char *r);
  81. extern char * re_comp(char *pat);
  82. extern int re_exec(char *lp);
  83.  
  84. /*
  85.  * wcmatch - Match string s against template containing widlcards
  86.  *
  87.  *         WCMATCH takes a string and a template, and returns
  88.  *         true if the string matches the template, and
  89.  *         FALSE otherwise.
  90.  *
  91.  *    ARGS:  s        - string to be tested
  92.  *           template - Template containing optional wildcards
  93.  *
  94.  * RETURNS:  TRUE (non-zero) on match.  FALSE (0) otherwise.
  95.  *
  96.  *    NOTE:  If template is NULL, will return TRUE.
  97.  *
  98.  */
  99. int
  100. wcmatch(char *s, char *template)
  101. //    char    *s;
  102. //    char    *template;
  103.     {
  104.     char    temp[200];
  105.     char    *p = temp;
  106.  
  107.     if(!template) return(TRUE);
  108.     *p++ = '^';
  109.  
  110.     while(*template) {
  111.         if(*template == '*') {*(p++)='.'; *(p++) = *(template++);}
  112.         else if(*template == '?') {*(p++)='.';template++;}
  113.         else if(*template == '.') {*(p++)='\\';*(p++)='.';template++;}
  114.         else if(*template == '[') {*(p++)='\\';*(p++)='[';template++;}
  115.         else if(*template == '$') {*(p++)='\\';*(p++)='$';template++;}
  116.         else if(*template == '^') {*(p++)='\\';*(p++)='^';template++;}
  117.         else if(*template == '\\') {*(p++)='\\';*(p++)='\\';template++;}
  118.         else *(p++) = *(template++);
  119.     }
  120.  
  121.     *p++ = '$';
  122.     *p++ = '\0';
  123.  
  124.     if(re_comp(temp)) return(FALSE);
  125.  
  126. #ifdef AUX
  127.     if (re_exec(s) == (char *)NULL)
  128.       return 0;
  129.     return 1;
  130. #else
  131.     return(re_exec(s));
  132. #endif
  133.     }
  134.  
  135. /*
  136.  * ul_insert - Insert a union link at the right location
  137.  *
  138.  *             UL_INSERT takes a directory and a union link to be added
  139.  *             to a the list of union links in the directory.  It then
  140.  *             inserts the union link in the right spot in the linked
  141.  *             list of union links associated with that directory.
  142.  *
  143.  *           If an identical link already exists, then the link which
  144.  *             would be evaluated earlier (closer to the front of the list)
  145.  *             wins and the other one is freed.  If this happens, an error
  146.  *             will also be returned.
  147.  *        
  148.  *    ARGS:    ul    - link to be inserted
  149.  *           vd    - directory to get link
  150.  *             p     - vl that this link will apper after
  151.  *                     NULL - This vl will go at end of list
  152.  *                     vd   - This vl will go at head of list
  153.  *
  154.  * RETURNS:    Success, or UL_INSERT_ALREADY_THERE or UL_INSERT_SUPERSEDING
  155.  */
  156. int
  157. ul_insert(VLINK ul, PVDIR vd,VLINK p)
  158. //    VLINK    ul;        /* Link to be inserted                   */
  159. //    PVDIR    vd;        /* Directory to receive link             */
  160. //    VLINK    p;        /* Union link to appear prior to new one */
  161.     {
  162.     VLINK    current;
  163.  
  164.     /* This is the first ul in the directory */
  165.     if(vd->ulinks == NULL) {
  166.         vd->ulinks = ul;
  167.         ul->previous = NULL;
  168.         ul->next = NULL;
  169.         return(PSUCCESS);
  170.     }
  171.  
  172.     /* This ul will go at the head of the list */
  173.     if(p == (VLINK) vd) {
  174.         ul->next = vd->ulinks;
  175.         ul->next->previous = ul;
  176.         vd->ulinks = ul;
  177.         ul->previous = NULL;
  178.     }
  179.     /* Otherwise, decide if it must be inserted at all  */
  180.     /* If an identical link appears before the position */
  181.     /* at which the new one is to be inserted, we can   */
  182.     /* return without inserting it                 */
  183.     else {
  184.         current = vd->ulinks;
  185.  
  186.         while(current) {
  187.         /* p == NULL means we insert after last link */
  188.         if(!p && (current->next == NULL))
  189.             p = current;
  190.  
  191.         if(vl_comp(current,ul) == 0) {
  192.             vlfree(ul);
  193.             return(UL_INSERT_ALREADY_THERE);
  194.         }
  195.  
  196.         if(current == p) break;
  197.         current = current->next;
  198.         }
  199.  
  200.         /* If current is null, p was not found */
  201.         if(current == NULL)
  202.         return(UL_INSERT_POS_NOTFOUND);
  203.  
  204.         /* Insert ul */
  205.         ul->next = p->next;
  206.         p->next = ul;
  207.         ul->previous = p;
  208.         if(ul->next) ul->next->previous = ul;
  209.     }
  210.  
  211.     /* Check for identical links after ul */
  212.     current = ul->next;
  213.  
  214.     while(current) {
  215.         if(vl_comp(current,ul) == 0) {
  216.         current->previous->next = current->next;
  217.         if(current->next)
  218.             current->next->previous = current->previous;
  219.         vlfree(current);
  220.         return(UL_INSERT_SUPERSEDING);
  221.         }
  222.         current = current->next;
  223.     }
  224.     
  225.     return(PSUCCESS);
  226.     }
  227.  
  228. /*
  229.  * vl_insert - Insert a directory link at the right location
  230.  *
  231.  *             VL_INSERT takes a directory and a link to be added to a 
  232.  *             directory and inserts it in the linked list of links for
  233.  *             that directory.  
  234.  *
  235.  *             If a link already exists with the same name, and if the
  236.  *             information associated with the new link matches that in
  237.  *             the existing link, an error is returned.  If the information
  238.  *             associated with the new link is different, but the magic numbers
  239.  *             match, then the new link will be added as a replica of the
  240.  *             existing link.  If the magic numbers do not match, the new
  241.  *             link will only be added to the list of "replicas" if the
  242.  *             allow_conflict flag has been set.
  243.  * 
  244.  *             If the link is not added, an error is returned and the link
  245.  *             is freed.  Ordering for the list of links is by the link name.  
  246.  *        
  247.  *             If vl is a union link, then VL_INSERT calls ul_insert with an
  248.  *           added argument indicating the link is to be included at the
  249.  *             end of the union link list.
  250.  * 
  251.  *    ARGS:    vl - Link to be inserted, vd - directory to get link
  252.  *             allow_conflict - insert links with conflicting names
  253.  *
  254.  * RETURNS:    Success, or VL_INSERT_ALREADY_THERE
  255.  */
  256. int
  257. vl_insert(VLINK vl, PVDIR vd,int allow_conflict)
  258. //    VLINK    vl;        /* Link to be inserted               */
  259. //    PVDIR    vd;        /* Directory to receive link         */
  260. //    int        allow_conflict;    /* Allow duplicate names             */
  261.     {
  262.     VLINK    current;    /* To step through list             */
  263.     VLINK    crep;        /* To step through list of replicas  */
  264.     int    retval;        /* Temp for checking returned values */
  265.  
  266.     /* This can also be used to insert union links at end of list */
  267.     if(vl->linktype == 'U') return(ul_insert(vl,vd,NULL));
  268.  
  269.     /* If this is the first link in the directory */
  270.     if(vd->links == NULL) {
  271.         vd->links = vl;
  272.         vl->previous = NULL;
  273.         vl->next = NULL;
  274.         vd->lastlink = vl;
  275.         return(PSUCCESS);
  276.     }
  277.  
  278.     /* If no sorting is to be done, just insert at end of list */
  279.     if(allow_conflict == VLI_NOSORT) {
  280.         vd->lastlink->next = vl;
  281.         vl->previous = vd->lastlink;
  282.         vl->next = NULL;
  283.         vd->lastlink = vl;
  284.         return(PSUCCESS);
  285.     }
  286.  
  287.     /* If it is to be inserted at start of list */
  288.     if(vl_comp(vl,vd->links) < 0) {
  289.         vl->next = vd->links;
  290.         vl->previous = NULL;
  291.         vl->next->previous = vl;
  292.         vd->links = vl;
  293.         return(PSUCCESS);
  294.     }
  295.  
  296.     current = vd->links;
  297.  
  298.     /* Otherwise, we must find the right spot to insert it */
  299.     while((retval = vl_comp(vl,current)) > 0) {
  300.         if(!current->next) {
  301.         /* insert at end */
  302.         vl->previous = current;
  303.         vl->next = NULL;
  304.         current->next = vl;
  305.         vd->lastlink = vl;
  306.         return(PSUCCESS);
  307.         }
  308.         current = current->next;
  309.     }
  310.  
  311.     /* If we found an equivilant entry already in list */
  312.     if(!retval) {
  313.         if(vl_equal(vl,current)) {
  314.         vlfree(vl);
  315.         return(VL_INSERT_ALREADY_THERE);
  316.         }
  317.         if((allow_conflict == VLI_NOCONFLICT) &&
  318.            ((vl->f_magic_no != current->f_magic_no) ||
  319.         (vl->f_magic_no==0)))
  320.         return(VL_INSERT_CONFLICT);
  321.         /* Insert the link into the list of "replicas" */
  322.         /* If magic is 0, then create a pseudo magic number */
  323.         if(vl->f_magic_no == 0) vl->f_magic_no = -1;
  324.         crep = current->replicas;
  325.         if(!crep) {
  326.         current->replicas = vl;
  327.         vl->next = NULL;
  328.         vl->previous = NULL;
  329.         }
  330.         else {
  331.         while(crep->next) {
  332.             /* If magic was 0, then we need a unique magic number */
  333.             if((crep->f_magic_no < 0) && (vl->f_magic_no < 1))
  334.             (vl->f_magic_no)--;
  335.             crep = crep->next;
  336.         }
  337.         /* If magic was 0, then we need a unique magic number */
  338.         if((crep->f_magic_no < 0) && (vl->f_magic_no < 1))
  339.             (vl->f_magic_no)--;
  340.         crep->next = vl;
  341.         vl->previous = crep;
  342.         vl->next = NULL;
  343.         }
  344.         return(PSUCCESS);
  345.     }
  346.  
  347.     /* We found the spot where vl is to be inserted */
  348.     vl->next = current;
  349.     vl->previous = current->previous;
  350.     current->previous = vl;
  351.     vl->previous->next = vl;
  352.     return(PSUCCESS);
  353.     }
  354.  
  355. /*
  356.  * nlsindex - Find first instance of string 2 in string 1 following newline
  357.  *
  358.  *          NLSINDEX scans string 1 for the first instance of string
  359.  *          2 that immediately follows a newline.  If found, NLSINDEX
  360.  *          returns a pointer to the first character of that instance.
  361.  *          If no instance is found, NLSINDEX returns NULL (0).
  362.  *
  363.  *    NOTE:   This function is only useful for searching strings that
  364.  *            consist of multiple lines.  s1 is assumed to be preceeded
  365.  *           by a newline.  Thus, if s2 is at the start of s1, it will
  366.  *          be found.
  367.  *    ARGS:   s1 - string to be searched
  368.  *            s2 - string to be found
  369.  * RETURNS:   First instance of s2 in s1, or NULL (0) if not found
  370.  */
  371. char *
  372. nlsindex(char * s1, char *s2)
  373. //    char    *s1;        /* String to be searched */
  374. //    char    *s2;        /* String to be found    */
  375.     {
  376.     register int s2len = strlen(s2);
  377.     char    *curline = s1;    /* Pointer to start of current line */
  378.  
  379.     /* In case s2 appears at start of s1 */
  380.     if(strncmp(curline,s2,s2len) == 0)
  381.         return(curline);
  382.  
  383.     /* Check remaining lines of s1 */
  384.     while((curline = (char *) index(curline,'\n')) != NULL) {
  385.         curline++;
  386.         if(strncmp(curline,s2,s2len) == 0)
  387.         return(curline);
  388.     }
  389.  
  390.     /* We didn't find it */
  391.     return(NULL);
  392.     }
  393.  
  394. /*
  395.  * month_sname - Return a month name from it's number
  396.  *
  397.  *               MONTH_SNAME takes a number in the range 0
  398.  *               to 12 and returns a pointer to a string
  399.  *               representing the three letter abbreviation
  400.  *             for that month.  If the argument is out of 
  401.  *         range, MONTH_SNAME returns a pointer to "Unk".
  402.  *
  403.  *       ARGS:   n - Number of the month
  404.  *    RETURNS:   Abbreviation for selected month
  405.  */
  406. char *month_sname(int n)
  407. //    int n;        /* Month number */
  408. {
  409.     static char *name[] = { "Unk",
  410.         "Jan","Feb","Mar","Apr","May","Jun",
  411.         "Jul","Aug","Sep","Oct","Nov","Dec"
  412.     };
  413.     return((n < 1 || n > 12) ? name[0] : name[n]);
  414. }
  415.  
  416. /*
  417.  * sindex - Find first instance of string 2 in string 1
  418.  *
  419.  *          SINDEX scans string 1 for the first instance of string
  420.  *          2.  If found, SINDEX returns a pointer to the first
  421.  *          character of that instance.  If no instance is found,
  422.  *          SINDEX returns NULL (0).
  423.  *
  424.  *    ARGS:   s1 - string to be searched
  425.  *            s2 - string to be found
  426.  * RETURNS:   First instance of s2 in s1, or NULL (0) if not found
  427.  */
  428. char *
  429. sindex(char *s1, char * s2)
  430. //    char    *s1;        /* String to be searched   */
  431. //    char    *s2;        /* String to be found      */
  432.     {
  433.     register int s2len = strlen(s2);
  434.     char    *s = s1;    /* Temp pointer to string  */
  435.  
  436.     /* Check for first character of s2 */
  437.     while((s = (char *) index(s,*s2)) != NULL) {
  438.         if(strncmp(s,s2,s2len) == 0)
  439.         return(s);
  440.         s++;
  441.     }
  442.  
  443.     /* We didn't find it */
  444.     return(NULL);
  445.     }
  446.  
  447. int
  448. scan_error(char * erst)
  449. //    char    *erst;
  450.     {
  451.     *p_err_string = '\0';
  452.  
  453.     if(strncmp(erst,"NOT-A-DIRECTORY",15) == 0)
  454.         return(DIRSRV_NOT_DIRECTORY);
  455.  
  456.     if(strncmp(erst,"UNIMPLEMENTED",13) == 0) {
  457.         perrno = DIRSRV_UNIMPLEMENTED;
  458.         sscanf(erst+13,"%*[^\n \t\r]%*[ \t]%[^\n]",p_err_string);
  459.         return(perrno);
  460.     }
  461.  
  462.     if(strncmp(erst,"WARNING ",8) == 0) {
  463.         erst += 8;
  464.         *p_warn_string = '\0';
  465.         sscanf(erst,"%*[^\n \t\r]%*[ \t]%[^\n]",p_warn_string);
  466.         /* Return values for warnings are negative */
  467.         if(strncmp(erst,"OUT-OF-DATE",11) == 0) {
  468.         pwarn = PWARN_OUT_OF_DATE;
  469.         return(PSUCCESS);
  470.         }
  471.         if(strncmp(erst,"MESSAGE",7) == 0) {
  472.         pwarn = PWARN_MSG_FROM_SERVER;
  473.         return(PSUCCESS);
  474.         }
  475.         pwarn = PWARNING;
  476.         sscanf(erst,"%[^\n]",p_warn_string);
  477.         return(PSUCCESS);
  478.     }
  479.     else if(strncmp(erst,"ERROR",5) == 0) {
  480.         if(*(erst+5)) sscanf(erst+6,"%[^\n]",p_err_string);
  481.         perrno = DIRSRV_ERROR;
  482.         return(perrno);
  483.     }
  484.     /* The rest start with "FAILURE" */
  485.     else if(strncmp(erst,"FAILURE",7) != 0) {
  486.         /* Unrecognized - Give warning, but return PSUCCESS */
  487.         if(pwarn == 0) {
  488.         *p_warn_string = '\0';
  489.         pwarn = PWARN_UNRECOGNIZED_RESP;
  490.         sscanf(erst,"%[^\n]",p_warn_string);
  491.         }
  492.         return(PSUCCESS);
  493.     }
  494.  
  495.     if(strncmp(erst,"FAILURE ",8) != 0) {
  496.         perrno = PFAILURE;
  497.         return(perrno);
  498.     }    
  499.     erst += 8;
  500.     
  501.     sscanf(erst,"%*[^\n \t\r]%*[ \t]%[^\n]",p_err_string);
  502.  
  503.     /* Still to add               */
  504.     /* DIRSRV_AUTHENT_REQ     242 */
  505.     /* DIRSRV_BAD_VERS        245 */
  506.  
  507.     if(strncmp(erst,"NOT-FOUND",9) == 0) 
  508.         perrno = DIRSRV_NOT_FOUND;
  509.     else if(strncmp(erst,"NOT-AUTHORIZED",13) == 0) 
  510.         perrno = DIRSRV_NOT_AUTHORIZED;
  511.     else if(strncmp(erst,"ALREADY-EXISTS",14) == 0) 
  512.         perrno = DIRSRV_ALREADY_EXISTS;
  513.     else if(strncmp(erst,"NAME-CONFLICT",13) == 0) 
  514.         perrno = DIRSRV_NAME_CONFLICT;
  515.     else if(strncmp(erst,"SERVER-FAILED",13) == 0) 
  516.         perrno = DIRSRV_SERVER_FAILED;
  517.      /* Use it whether it starts with FAILURE or not */
  518.     else if(strncmp(erst,"NOT-A-DIRECTORY",15) == 0) 
  519.         perrno = DIRSRV_NOT_DIRECTORY;
  520.     else perrno = PFAILURE;
  521.  
  522.     return(perrno);
  523.     }
  524.  
  525. PATTRIB
  526. parse_attribute(char *line)
  527. //    char    *line;
  528.     {
  529.     char    l_precedence[MAX_DIR_LINESIZE];
  530.     char    l_name[MAX_DIR_LINESIZE];
  531.     char    l_type[MAX_DIR_LINESIZE];
  532.     char    l_value[MAX_DIR_LINESIZE];
  533.     PATTRIB    at;
  534.     int    tmp;
  535.  
  536.     tmp = sscanf(line,"OBJECT-INFO %s %s %[^\n]", l_name, l_type, l_value);
  537.     
  538.     if(tmp < 3) {
  539.         tmp = sscanf(line,"LINK-INFO %s %s %s %[^\n]", l_precedence,
  540.              l_name, l_type, l_value);
  541.         if(tmp < 4) {
  542.         perrno = DIRSRV_BAD_FORMAT;
  543.         return(NULL);
  544.         }
  545.     }
  546.  
  547.     at = atalloc();
  548.  
  549.     if(tmp == 4) {
  550.         if(strcmp(l_precedence,"CACHED") == 0) 
  551.         at->precedence = ATR_PREC_CACHED;
  552.         else if(strcmp(l_precedence,"LINK") == 0) 
  553.         at->precedence = ATR_PREC_LINK;
  554.         else if(strcmp(l_precedence,"REPLACEMENT") == 0) 
  555.         at->precedence = ATR_PREC_REPLACE;
  556.         else if(strcmp(l_precedence,"ADDITIONAL") == 0) 
  557.         at->precedence = ATR_PREC_ADD;
  558.     }
  559.  
  560.     at->aname = stcopy(l_name);
  561.     at->avtype = stcopy(l_type);
  562.     if(strcmp(l_type,"ASCII") == 0) 
  563.         at->value.ascii = stcopy(l_value);
  564.     else if(strcmp(l_type,"LINK") == 0) {
  565.         char        ftype[MAX_DIR_LINESIZE];
  566.         char        lname[MAX_DIR_LINESIZE];
  567.         char        htype[MAX_DIR_LINESIZE];
  568.         char        host[MAX_DIR_LINESIZE];
  569.         char        ntype[MAX_DIR_LINESIZE];
  570.         char        fname[MAX_DIR_LINESIZE];
  571.         VLINK        al;
  572.  
  573.         al = vlalloc();
  574.         at->value.link = al;
  575.  
  576.         tmp = sscanf(l_value,"%c %s %s %s %s %s %s %d %d",
  577.              &(al->linktype),
  578.              ftype,lname,htype,host,ntype,fname,
  579.              &(al->version),
  580.              &(al->f_magic_no));
  581.         if(tmp == 9) {
  582.         al->type = stcopyr(ftype,al->type);
  583.         al->name = stcopyr(unquote(lname),al->name);
  584.         al->hosttype = stcopyr(htype,al->hosttype);
  585.         al->host = stcopyr(host,al->host);
  586.         al->nametype = stcopyr(ntype,al->nametype);
  587.         al->filename = stcopyr(fname,al->filename);
  588.         }
  589.         else {
  590.         perrno = DIRSRV_BAD_FORMAT;
  591.         return(NULL);
  592.         }
  593.         
  594.     }
  595.  
  596.     return(at);
  597.     }
  598.  
  599. /*
  600.  * nxtline - Find the next line in the string
  601.  *
  602.  *          NXTLINE takes a string and returns a pointer to
  603.  *          the character immediately following the next newline.
  604.  *
  605.  *    ARGS:   s - string to be searched
  606.  *
  607.  * RETURNS:   Next line or NULL (0) on failure
  608.  */
  609. char *
  610. nxtline(char *s)
  611. //    char    *s;        /* String to be searched */
  612.  {
  613.     s = (char *) index(s,'\n');
  614.     if(s) return(++s);
  615.     else return(NULL);
  616.     }
  617.  
  618.  
  619. /*
  620.  * unquote - unquote string if necessary
  621.  *
  622.  *          UNQUOTE takes a string and unquotes it if it has been quoted.
  623.  *
  624.  *    ARGS:   s - string to be unquoted
  625.  *
  626.  * RETURNS:   The original string.  If the string has been quoted, then the
  627.  *            result appears in static storage, and must be copied if 
  628.  *            it is to last beyond the next call to quote.
  629.  *
  630.  */
  631. char *
  632. unquote(char *s)
  633. //    char    *s;        /* String to be quoted */
  634.     {
  635.     static char    unquoted[200];
  636.     char        *c = unquoted;
  637.  
  638.     if(*s != '\'') return(s);
  639.  
  640.     s++;
  641.  
  642.     /* This should really treat a quote followed by other */
  643.     /* than a quote or a null as an error                 */
  644.     while(*s) {
  645.         if(*s == '\'') s++;
  646.         if(*s) *c++ = *s++;
  647.     }
  648.  
  649.     *c++ = '\0';
  650.  
  651.     return(unquoted);
  652.     }
  653.  
  654. #if defined(DEBUG) && defined(STRSPN)
  655. /* needed for -D option parsing */
  656. /*
  657.  * strspn - Count initial characters from chrs in s
  658.  *
  659.  *          STRSPN counts the occurances of chacters from chrs
  660.  *            in the string s preceeding the first occurance of
  661.  *            a character not in s.
  662.  *
  663.  *    ARGS:   s    - string to be checked
  664.  *            chrs - string of characters we are looking for
  665.  *
  666.  * RETURNS:   Count of initial characters from chrs in s
  667.  */
  668. strspn(char *s, char *chrs)
  669. //    char    *s;    /* String to search                         */
  670. //    char    *chrs; /* String of characters we are looking for  */
  671.     {
  672.     char    *cp;   /* Pointer to the current character in chrs */
  673.     int    count; /* Count of characters seen so far          */
  674.  
  675.     count = 0;
  676.  
  677.     while(*s) {
  678.         for(cp = chrs;*cp;cp++)
  679.         if(*cp == *s) {
  680.             s++;
  681.             count++;
  682.             goto done;
  683.         }
  684.         return(count);
  685.     done:
  686.         ;
  687.     }
  688.     return(count);
  689.     }
  690. #endif
  691.  
  692. #ifdef CUTCP
  693. char
  694. *inet_ntoa(struct in_addr in)
  695. {
  696.     static    char    buff[36];
  697.  
  698.     unsigned char    *c = (char *) &in.address;
  699.     sprintf(buff,"%d.%d.%d.%d",*c,*(c+1),*(c+2),*(c+3));
  700.     return(buff);
  701. }
  702.  
  703. long
  704. inet_addr(char *cp)
  705. {
  706.     long    value = 0;
  707.     unsigned    v1,v2,v3,v4;
  708.  
  709.     v1 = v2 = v3 = v4 = 0xff;
  710.     sscanf(cp,"%d.%d.%d.%d",&v1,&v2,&v3,&v4);
  711.     value = (v1 << 24) | (v2 << 16) | (v3 << 8) | v4;
  712.     return(value);
  713. }
  714.  
  715. struct    hostent
  716. *gethostbyname(char *name)
  717. {
  718.     struct machinfo    *mp;
  719.     int    mnum;
  720.     unsigned long    now;
  721.     static    struct hostent    ht;
  722.     extern int pfs_debug;
  723.  
  724.     mp = Shostlook(name);
  725.     if(!mp || (!mp->hostip[0])) {    /* DNS lookup */
  726. #ifdef DEBUG
  727.         if (pfs_debug)
  728.         fprintf(stderr, "Domain name lookup of %s\n", name);
  729. #endif
  730.         mnum = Sdomain(name);        /* start a DNS lookup */
  731.         now = time(NULL) + NS_TIMEOUT;
  732.         while(now > time(NULL)) {
  733.             int    i, class, dat;
  734.  
  735.             Stask();
  736.             i = Sgetevent(USERCLASS, &class, &dat);
  737.             if(i == DOMOK) {    /* domain lookup ok */
  738.                 mp = Slooknum(mnum);
  739. #ifdef DEBUG
  740.         if (pfs_debug)
  741.         fprintf(stderr, "Domain name lookup of %s Completed OK\n", name);
  742. #endif
  743.                 break;
  744.             }
  745.         }
  746.         if(!mp)    {    /* get here if timeout */
  747. #ifdef DEBUG
  748.         if (pfs_debug)
  749.         fprintf(stderr, "Domain name lookup of %s Failed\n", name);
  750. #endif
  751.             return(NULL);
  752.         }
  753.     }
  754.     ht.h_addr = *((unsigned long *) mp->hostip);
  755.     ht.h_length = 4;
  756.     ht.h_addrtype = AF_INET;
  757.     return(&ht);
  758.  
  759. }
  760. #endif /* CUTCP */
  761.  
  762. #ifdef GETENV
  763. /*
  764.  * Copyright (c) 1987 Regents of the University of California.
  765.  * All rights reserved.
  766.  *
  767.  * Redistribution and use in source and binary forms are permitted
  768.  * provided that: (1) source distributions retain this entire copyright
  769.  * notice and comment, and (2) distributions including binaries display
  770.  * the following acknowledgement:  ``This product includes software
  771.  * developed by the University of California, Berkeley and its contributors''
  772.  * in the documentation or other materials provided with the distribution
  773.  * and in all advertising materials mentioning features or use of this
  774.  * software. Neither the name of the University nor the names of its
  775.  * contributors may be used to endorse or promote products derived
  776.  * from this software without specific prior written permission.
  777.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  778.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  779.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  780.  */
  781.  
  782. #if defined(LIBC_SCCS) && !defined(lint)
  783. static char sccsid[] = "@(#)getenv.c    5.7 (Berkeley) 6/1/90";
  784. #endif /* LIBC_SCCS and not lint */
  785.  
  786. #include <stdlib.h>
  787. #include <stddef.h>
  788.  
  789. /*
  790.  * getenv --
  791.  *    Returns ptr to value associated with name, if any, else NULL.
  792.  */
  793. char *
  794. getenv(name)
  795.     char *name;
  796. {
  797.     int offset;
  798.     char *_findenv();
  799.  
  800.     return(_findenv(name, &offset));
  801. }
  802.  
  803. /*
  804.  * _findenv --
  805.  *    Returns pointer to value associated with name, if any, else NULL.
  806.  *    Sets offset to be the offset of the name/value combination in the
  807.  *    environmental array, for use by setenv(3) and unsetenv(3).
  808.  *    Explicitly removes '=' in argument name.
  809.  *
  810.  *    This routine *should* be a static; don't use it.
  811.  */
  812. char *
  813. _findenv(name, offset)
  814.     register char *name;
  815.     int *offset;
  816. {
  817.     extern char **environ;
  818.     register int len;
  819.     register char **P, *C;
  820.  
  821.     for (C = name, len = 0; *C && *C != '='; ++C, ++len);
  822.     for (P = environ; *P; ++P)
  823.         if (!strncmp(*P, name, len))
  824.             if (*(C = *P + len) == '=') {
  825.                 *offset = P - environ;
  826.                 return(++C);
  827.             }
  828.     return(NULL);
  829. }
  830. #endif
  831.